package com.qqt.csr.archive.batch.task.etl.reader;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.qqt.csr.archive.batch.task.context.ConversationArchiveTaskContext;
import com.qqt.csr.archive.batch.task.etl.BaseArchiveReader;
import com.qqt.csr.archive.entity.reader.*;
import com.qqt.csr.archive.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.item.ItemReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @Author: yang hao
 * @Date: 2024/11/20 10:17
 * @Description: 会话归档 读取器
 **/
@Slf4j
@Component
@SuppressWarnings("unused")
public class ConversationArchiveReader extends BaseArchiveReader<ConversationArchiveTaskContext> implements ItemReader<ConversationArchiveTaskContext> {

    @Autowired
    private ArtificialConversationService artificialConversationService;
    @Autowired
    private SmartConversationService smartConversationService;
    @Autowired
    private ImH5ManageService imH5ManageService;
    @Autowired
    private CsrRoomMemberService csrRoomMemberService;
    @Autowired
    private CsrImAccountService csrImAccountService;
    @Autowired
    private SysUserService sysUserService;


    private static final String USER_TYPE_CUSTOMER = "1";
    private static final String USER_TYPE_USER = "0";

    /**
     * 读取会话数据
     * @return {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    @Override
    public ConversationArchiveTaskContext read() {
        // 读取会话数据
        ConversationArchiveTaskContext context = conversationArchiveTaskContexts.poll();
        if (context == null) {
            return null;
        }
        // 根据来源类型处理会话数据读取
        switch (context.getSource()) {
            // 处理人工会话数据读取
            case ARTIFICIAL: doArtificialRead(context); break;
            // 处理自能会话数据读取
            case SMART: doSmartRead(context); break;
            // 抛出异常
            default: throw new IllegalArgumentException("不支持的来源类型" + context.getSource());
        }
        return context;
    }

    /**
     * 处理人工会话数据读取
     * @param context {@link ConversationArchiveTaskContext} 任务上下文
     */
    private void doArtificialRead(ConversationArchiveTaskContext context) {
        log.debug("开始读取人工会话数据, 上下文:{}", context.toJsonString());
        // 加载人工会话数据
        loadArtificialConversation(context);
        // 加载渠道数据
        loadArtificialChannel(context);
        // 加载房间成员数据 账户数据
        loadArtificialAccount(context);
        // 加载客服数据
        loadCsAccount(context);
        log.debug("读取人工会话数据完毕, 上下文:{}", context.toJsonString());
    }

    /**
     * 加载人工会话数据
     * @param context {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    private void loadArtificialConversation(ConversationArchiveTaskContext context) {
        // 加载人工会话数据
        ArtificialConversation conversation = artificialConversationService.getById(context.getConversationId());
        // 判断人工会话数据是否存在, 不存在则抛出异常
        Optional.ofNullable(conversation).orElseThrow(() -> new IllegalArgumentException("人工会话数据不存在" + context.getConversationId()));
        // 加入上下文
        context.setArtificialConversation(conversation);
    }

    /**
     * 处理智能会话数据读取
     * @param context {@link ConversationArchiveTaskContext} 任务上下文
     */
    private void doSmartRead(ConversationArchiveTaskContext context) {
        log.debug("开始读取智能会话数据, 上下文:{}", context.toJsonString());
        // 加载智能会话数据
        loadSmartConversation(context);
        // 加载智能会话账户数据
        loadSmartAccount(context);
        log.debug("读取智能会话数据完毕, 上下文:{}", JSONUtil.toJsonStr(context));
    }

    /**
     * 加载渠道数据
     * @param context {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    private void loadArtificialChannel(ConversationArchiveTaskContext context) {
        // 从上下文中获取人工会话数据
        ArtificialConversation conversation = context.getArtificialConversation();
        // 获取人工会话的扩展数据
        String ext = conversation.getExt();
        // 判断扩展数据是否为空或JSON对象, 不是则返回
        if (StrUtil.isBlank(ext) || !JSONUtil.isTypeJSONObject(ext)) {
            return;
        }
        // 解析扩展数据
        JSONObject extJson = JSONUtil.parseObj(conversation.getExt());
        String channelId = extJson.getStr("channelId", null);
        // 判断渠道ID是否为空, 为空则返回
        if (StrUtil.isBlank(channelId)) {
            return;
        }
        // 加载渠道数据
        ImH5Manage channel = imH5ManageService.getById(channelId);
        // 加入上下文
        context.setChannel(channel);
    }

    /**
     * 加载房间成员数据 账户数据
     * @param context {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    private void loadArtificialAccount(ConversationArchiveTaskContext context) {
        // 从上下文中获取人工会话数据
        ArtificialConversation conversation = context.getArtificialConversation();
        // 加载房间成员数据, 不存在则返回
        List<CsrRoomMember> roomMembers = csrRoomMemberService.getRoomMembers(conversation.getRoomId());
        if (roomMembers.isEmpty()) {
            return;
        }
        // 加载房间成员账户数据, 不存在则返回
        List<String> accountIds = roomMembers.stream().map(CsrRoomMember::getAccountId).toList();
        List<CsrImAccount> accounts = csrImAccountService.getByIds(accountIds);
        if (accounts.isEmpty()) {
            return;
        }

        // 根据账户数据过滤出客服数据
        Optional<CsrImAccount> csAccountOpt = accounts.stream()
                .filter(account -> Objects.nonNull(account.getExt()) && USER_TYPE_CUSTOMER.equals(account.getExt().getUserType()))
                .findFirst();

        Optional<CsrImAccount> userAccountOpt = accounts.stream()
                .filter(account -> Objects.nonNull(account.getExt()) && USER_TYPE_USER.equals(account.getExt().getUserType()))
                .findFirst();

        CsrImAccount csAccount = csAccountOpt.orElse(null);
        CsrImAccount userAccount = userAccountOpt.orElse(null);

        // 加入上下文
        context.setCsAccount(csAccount);
        context.setUserAccount(userAccount);
    }

    /**
     * 加载客服数据
     * @param context {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    private void loadCsAccount(ConversationArchiveTaskContext context) {
        // 从上下文中获取人工会话 客服数据, 不存在则返回
        CsrImAccount csAccount = context.getCsAccount();
        if (csAccount == null) {
            return;
        }
        String csId = csAccount.getExt().getCsId();
        SysUser sysUser = sysUserService.getById(csId);
        context.setSysUser(sysUser);
    }

    /**
     * 加载智能会话数据
     * @param context {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    private void loadSmartConversation(ConversationArchiveTaskContext context) {
        // 加载智能会话数据, 不存在则抛出异常
        SmartConversation conversation = smartConversationService.getById(context.getConversationId());
        Optional.ofNullable(conversation).orElseThrow(() -> new IllegalArgumentException("conversation is required"));
        // 加入上下文
        context.setSmartConversation(conversation);
    }

    /**
     * 加载智能会话账户数据
     * @param context {@link ConversationArchiveTaskContext} 会话归档任务上下文
     */
    private void loadSmartAccount(ConversationArchiveTaskContext context) {
        // 从上下文中获取智能会话数据
        SmartConversation conversation = context.getSmartConversation();
        // 查询访客和机器人是否存在账户信息
        String visitorId = conversation.getVisitorId();
        String robotId = String.valueOf(conversation.getRebotId());
        CsrImAccount visitor = csrImAccountService.getAccountByUserId(visitorId, 0, conversation.getChannelId().toString());
        CsrImAccount robot = csrImAccountService.getAccountByUserId(robotId, 2, conversation.getChannelId().toString());
        // 加入上下文
        context.setUserAccount(visitor);
        context.setCsAccount(robot);
    }

}
